package com.yunfeisoft.common.file;

import com.yunfeisoft.common.utils.KeyUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

import java.io.*;
import java.util.*;

/**
 * 本地磁盘保存文件
 * Created by Jackie Liu on 2017/4/23.
 */
public class LocalDiskFileOperation implements FileOperation, InitializingBean {

    private static final Logger log = LoggerFactory.getLogger(LocalDiskFileOperation.class);

    private String rootPath;
    private Map<String, Integer> fileMap = new HashMap<>();

    @Override
    public String save(File file) throws FileNotFoundException {
        if (!file.exists()) {
            throw new FileNotFoundException();
        }
        String logicName = KeyUtils.getKey() + "." + FilenameUtils.getExtension(file.getAbsolutePath());
        String filePath = weightPolling() + logicName;
        String absolutePath = rootPath + filePath;

        try (
                InputStream is = new FileInputStream(file);
                OutputStream os = new FileOutputStream(new File(absolutePath));
        ) {
            byte[] bs = new byte[1024];
            int len;
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
        } catch (IOException e) {
            log.error("保存文件失败", e);
        } finally {

        }

        /*InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream(file);
            os = new FileOutputStream(new File(absolutePath));

            byte[] bs = new byte[1024];
            int len;
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
        } catch (IOException e) {
            log.error("保存文件失败", e);
            return null;
        } catch (Exception e) {
            log.error("保存文件失败", e);
            return null;
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }*/
        return "/" + filePath;
    }

    @Override
    public String save(InputStream is, String logicName) {
        String filePath = weightPolling() + logicName;
        String absolutePath = rootPath + filePath;

        try (
                OutputStream os = new FileOutputStream(new File(absolutePath));
        ) {
            byte[] bs = new byte[1024];
            int len;
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
        } catch (IOException e) {
            log.error("保存文件失败", e);
        } finally {

        }

        /*OutputStream os = null;
        try {
            os = new FileOutputStream(new File(absolutePath));

            byte[] bs = new byte[1024];
            int len;
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
        } catch (IOException e) {
            log.error("保存文件失败", e);
            return null;
        } catch (Exception e) {
            log.error("保存文件失败", e);
            return null;
        } finally {
            IOUtils.closeQuietly(os);
        }*/
        return "/" + filePath;
    }

    @Override
    public byte[] read(String filePath) {
        File file = new File(rootPath + filePath);
        if (!file.exists()) {
            return null;
        }

        try (
                ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
                BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
        ) {
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, buf_size))) {
                bos.write(buffer, 0, len);
            }
        } catch (IOException e) {
            log.error("读取文件字节失败", e);
        } finally {

        }

        /*ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(file));
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, buf_size))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            log.error("读取文件字节失败", e);
        } finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(bos);
        }*/
        return null;
    }

    @Override
    public boolean remove(String filePath) {
        File file = new File(rootPath + filePath);
        if (!file.exists()) {
            return true;
        }
        return file.delete();
    }

    public String getRootPath() {
        return rootPath;
    }

    public void setRootPath(String rootPath) {
        this.rootPath = rootPath;
    }

    public String weightPolling() {
        Map<String, Integer> pollFileMap = new HashMap<String, Integer>();
        pollFileMap.putAll(fileMap);
        Set<String> keySet = pollFileMap.keySet();
        Iterator<String> it = keySet.iterator();
        List<String> serverList = new ArrayList<String>();
        while (it.hasNext()) {
            String server = it.next();
            Integer weight = pollFileMap.get(server);
            for (int i = 0; i < weight; i++) {
                serverList.add(server);
            }
        }
        Random random = new Random();
        int randomPos = random.nextInt(serverList.size());
        String filePath = serverList.get(randomPos);
        return filePath;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (rootPath == null) {
            rootPath = "/files/";
        }
        rootPath = rootPath.replace(File.separator, "/");
        if (!rootPath.endsWith("/")) {
            rootPath += "/";
        }
        File rootDir = new File(rootPath);
        if (rootDir.exists()) {
            File[] files = rootDir.listFiles();
            for (File dir : files) {
                if (!dir.isDirectory()) {
                    continue;
                }
                fileMap.put(dir.getName() + "/", dir.listFiles().length + 1);
            }
            return;
        }
        for (int i = 10; i < 30; i++) {
            File dir = new File(rootPath + String.valueOf(i));
            boolean success = dir.mkdirs();
            log.info("创建文件夹：" + rootPath + String.valueOf(i) + " result = " + success);
            fileMap.put(dir.getName() + "/", 1);
        }
    }
}
